package com.wlyy.bcwlw.sys;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.util.Assert;

import com.rework.joss.persistence.convention.utils.ConventionUtils;
import com.wlyy.bcwlw.common.utils.CookieUtils;
import com.wlyy.bcwlw.common.utils.SecurityUtil;
import com.wlyy.bcwlw.sys.user.entity.UserProfile;


/**
 * 
 * @ClassName. SecurityContextHolder
 * @Description. 安全上下文持有类
 * @author zhangyang
 * @date 2015年8月31日 下午2:44:04
 * @version V1.0
 */
public class SecurityContextHolder {
	// ~ Static fields/initializers
	// ==============================================
	// =======================================

	private static ThreadLocal contextHolder = new ThreadLocal<SecurityContext>();

	// ~ Methods
	// ================================================================
	// ========================================

	/**
	 * 
	* @Title. clearContext
	* @Description. 移除此线程上下文中当前线程的值。
	* @exception.
	 */
	public static void clearContext() {
		contextHolder.remove();
	}

	/**
	 * 
	* @Title. getContext
	* @Description. 返回此线程副本的值 无则新建副本
	* @return SecurityContext
	* @exception.
	 */
	public static SecurityContext getContext() {
		if (contextHolder.get() == null) {
			SecurityContext context = new SecurityContext();
			contextHolder.set(context);
			return context;
		}
		return (SecurityContext) contextHolder.get();
	}

	/**
	 * 
	* @Title. setContext
	* @Description.  将此线程局部变量的当前线程副本中的值设置为指定值。
	* @param context void
	* @exception.
	 */
	public static void setContext(SecurityContext context) {
		Assert.notNull(context,	"Only non-null Authentication instances are permitted");
		contextHolder.set(context);
	}
	
	/**
	 * 
	* @Title. setLoginContext
	* @Description. 设置登录信息上下文
	* @param request
	* @param response
	* @param userProfile
	* @param add2Cookie void
	* @exception.
	 */
	public static void setLoginContext(HttpServletRequest request, HttpServletResponse response,
			UserProfile userProfile, boolean add2Cookie) {
		request.setAttribute("userprofile", userProfile);
		setUser(request.getSession(), userProfile);
		SecurityContextHolder.getContext().setUserProfile(userProfile);
		SecurityContextHolder.getContext().setContextPathWithHost(
				request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath());
	}
	
	
	/**
	 * 
	* @Title. setLoginContext
	* @Description. 设置登录信息上下文
	* @param request
	* @param response
	* @param userProfile
	* @param add2Cookie void
	* @exception.
	 */
	public static void setLoginContextWithoutCookie(HttpServletRequest request, HttpServletResponse response,
			UserProfile userProfile) {
		request.setAttribute("userprofile", userProfile);
		setUser(request.getSession(), userProfile);
		SecurityContextHolder.getContext().setUserProfile(userProfile);
		SecurityContextHolder.getContext().setContextPathWithHost(
				request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath());
	}
	
	/**
	 * 
	* @Title. setLoginCookie
	* @Description. 设置登录cookie 
	* @param request
	* @param response
	* @param userProfile
	* @param cookieMaxAge 存活时间
	* @exception.
	 */
	public static void setLoginCookie(HttpServletRequest request, HttpServletResponse response, UserProfile userProfile, Integer cookieMaxAge) {
		setLoginCookie(request, response, cookieMaxAge, userProfile.getUserId());
	}
	
	/**
	 * 
	* @Title. setLoginCookie
	* @Description. 设置登录cookie 
	* @param request
	* @param response
	* @param userId void
	* @exception.
	 */
	public static void setLoginCookie(HttpServletRequest request, HttpServletResponse response, String userId) {
		setLoginCookie(request, response, -1, userId);
	}
	
	/**
	 * 
	* @Title. setLoginCookie
	* @Description. 设置登录cookie 
	* @param request
	* @param response
	* @param userId void
	* @exception.
	 */
	public static void setLoginCookie(HttpServletRequest request, HttpServletResponse response, Integer cookieMaxAge, String userId) {
		setUserData2Cookie(request, response, ConventionUtils.toMap(
				SecurityConst.AQ_AUTHENTICATION_COOKIE_KEY,
				userId,
				SecurityConst.AQ_AUTHENTICATION_COOKIE_KEY_SIGN,
				SecurityUtil.encodeCookieUserId(userId)
				), cookieMaxAge);
	}

	/**
	 * 
	* @Title. setLoginCookie
	* @Description. 设置登录上下文
	* @param request
	* @param response
	* @param userId void
	* @exception.
	 */
	public static void setLoginContext(HttpServletRequest request, HttpServletResponse response,
			UserProfile userProfile) {
		setLoginContextWithoutCookie(request, response, userProfile);
		setLoginCookie(request, response, userProfile, -1);
	}
	
	/**
	 * 
	* @Title. clearLoginContext
	* @Description. 清除登录上下文
	* @param request void
	* @exception.
	 */
	public static void clearLoginContext(HttpServletRequest request) {
		setUser(request.getSession(), UserProfile.ANONYMOUS);
		SecurityContextHolder.getContext().setUserProfile(UserProfile.ANONYMOUS);
		SecurityContextHolder.getContext().setContextPathWithHost(
				request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath());
		request.getSession().invalidate();
	}

	/**
	 * 
	* @Title. getUser
	* @Description. 从session中获得用户信息
	* @param session
	* @return UserProfile
	* @exception.
	 */
	public static UserProfile getUser(HttpSession session) {
		return (UserProfile) (session
				.getAttribute(SecurityConst.AQ_AUTHENTICATION_KEY));
	}

	/**
	 * 
	* @Title. setUser
	* @Description. 将用户信息放到session中
	* @param session
	* @param user void
	* @exception.
	 */
	public static void setUser(HttpSession session, UserProfile user) {
		session.setAttribute(SecurityConst.AQ_AUTHENTICATION_KEY, user);
	}

	/**
	 * 
	* @Title. getUserProfile
	* @Description. 返回当前用户
	* @return UserProfile
	* @exception.
	 */
	public static UserProfile getUserProfile() {
		if (null != getContext()) {
			return getContext().getUserProfile();
		}
		return UserProfile.ANONYMOUS;
	}
	
	/**
	 * 
	* @Title. isAnonymous
	* @Description. 判断当前用户是否为游客状态
	* @return boolean
	* @exception.
	 */
	public static boolean isAnonymous() {
		return UserProfile.ANONYMOUS.equals(getUserProfile());
	}
	
	/**
	 * 
	* @Title. setUserData2Cookie
	* @Description. 设置cookie用户信息
	* @param request
	* @param response
	* @param valuesMap
	* @param cookieMaxAge void
	* @exception.
	 */
	public static void setUserData2Cookie(HttpServletRequest request, HttpServletResponse response,Map valuesMap, Integer cookieMaxAge){
		Iterator iter= valuesMap.entrySet().iterator();
		while(iter.hasNext()){
			Entry entry = (Entry)iter.next();
			String key  = (String)entry.getKey();
			String value = (String)entry.getValue();
			if (SecurityConst.ANONYMOUS_ID.equals(value)) {
				return;
			}
			CookieUtils.setCookie(response, key, value, cookieMaxAge);
		}
	}
	
	/**
	 * 
	* @Title. getUserDataFromCookie
	* @Description. 从cookie获取用户信息
	* @param request
	* @param key
	* @return String
	* @exception.
	 */
	public static String getUserDataFromCookie(HttpServletRequest request,String key) {
		return CookieUtils.getCookie(request, key);
	}
	
	/**
	 * 
	* @Title. clearUserDataFromCookie
	* @Description. 清除用户cookie
	* @param response
	* @param key void
	* @exception.
	 */
	public static void clearUserDataFromCookie(HttpServletResponse response,String key) {
		CookieUtils.clearValue(response, key) ;
	}
	
	/**
	 * 
	* @Title. clearUserLoginInfo
	* @Description. 清除用户登录信息（包括所有cookie信息）
	* @param request
	* @param response void
	* @exception.
	 */
	public static void clearUserLoginInfo(HttpServletRequest request, HttpServletResponse response) {
		SecurityContextHolder.clearUserDataFromCookie(response, SecurityConst.AQ_AUTHENTICATION_COOKIE_KEY);
		SecurityContextHolder.clearUserDataFromCookie(response, SecurityConst.AQ_AUTHENTICATION_COOKIE_KEY_SIGN);
		SecurityContextHolder.clearUserDataFromCookie(response, SecurityConst.AQ_AUTHENTICATION_AUTOLOGIN_KEY);
		SecurityContextHolder.clearUserDataFromCookie(response, SecurityConst.USER_OPERATER_COOKIE_KEY);
		SecurityContextHolder.clearLoginContext(request);
	}
}
